#include "AC33Mxxx_conf.h"
#include "driver_header.h"


UART_BUFFER		sUart0Buffer; 
UART_BUFFER		sUart1Buffer; 
UART_BUFFER		sUart2Buffer; 
UART_BUFFER		sUart3Buffer; 

#ifdef WARNING_
UINT16	m_Temp = 0;
#endif


/**
*********************************************************************************************************
* @ Name : UART_Init
*
* @ Parameter
*		- uart_no : 0~2
*
*
*********************************************************************************************************
*/
void UART_Init (int uart_no,int bps)
{
	CSP_UART_T			*uart;
	UART_PROPERTY		uart_property; 
	UINT32				intr; 
	NVIC_IntrConfig		nvic_config; 

	
	//------------------------------------------------------------------------------
	// get UART object
	//------------------------------------------------------------------------------
	uart = UART_Get_Object (uart_no); 

	if (uart == (CSP_UART_T *) 0) return; 



	//------------------------------------------------------------------------------
	// configure GPIO 
	//------------------------------------------------------------------------------
	CSP_UART_ConfigureGPIO(uart); 


	//------------------------------------------------------------------------------
	// buffer setting
	//------------------------------------------------------------------------------
	UART_InitBuffer (uart_no); 	


	//------------------------------------------------------------------------------
	// soft reset 
	//
	//					no soft reset 
	//------------------------------------------------------------------------------


	//------------------------------------------------------------------------------
	// configure clock
	//
	//					done in CSP_UART_Init()
	//------------------------------------------------------------------------------


	//------------------------------------------------------------------------------
	// mode 
	//
	//					baudrate, data bits, stop bits, parity
	//------------------------------------------------------------------------------	
	uart_property.u32Baudrate = bps;
	uart_property.u16DataBits = 8; 
	uart_property.u8StopBits = 1; 
	uart_property.u8Parity = 0; 
	uart_property.u32Reference_clock = gSysClockInfo.PCLK; 
	CSP_UART_Init (uart, &uart_property); 


	//------------------------------------------------------------------------------
	// interrupt setting (peripheral)
	//
	//					
	//------------------------------------------------------------------------------	
	intr = (UART_INTR_RX|UART_INTR_TX|UART_INTR_LINE); 
	CSP_UART_ConfigureInterrupt (uart, intr, INTR_ENABLE); 
	


	//------------------------------------------------------------------------------
	// interrupt setting (interrupt module)
	//
	//					IRQ_UART0=38
	//					IRQ_UART1=39
	//					IRQ_UART2=40
	//					IRQ_UART2=41
	//
	//------------------------------------------------------------------------------		
	nvic_config.nIRQ_Number = (IRQ_UART0+uart_no); 
	nvic_config.u8Preemption_Priority= PRIO_UART0_PREEMPTION; 
	nvic_config.u8Subpriority= PRIO_UART0_SUBPRIORITY; 
	nvic_config.u8IntrEnable = INTR_ENABLE; 
	CSP_NVIC_ConfigureInterrupt (NVIC, &nvic_config); 




}




/**
*********************************************************************************************************
* @ Name : UART_Get_Object
*
* @ Parameter
*		- uart_no : 0~2
*
* @ Return 
*
*********************************************************************************************************
*/
CSP_UART_T* UART_Get_Object (int uart_no)
{

	CSP_UART_T *	p_obj; 


	switch (uart_no)
	{
	case 0: 
		p_obj = UART0; 
		break; 
		
	case 1: 
		p_obj = UART1; 
		break; 
		
	case 2: 
		p_obj = UART2; 
		break; 

	case 3: 
		p_obj = UART3;
		break; 

	default:
		p_obj = (CSP_UART_T *) 0; 
		break; 
	}


	return (p_obj); 

}



/**
*********************************************************************************************************
* @ Name : UART_InitBuffer
*
* @ Parameter
*		- uart_no : 0~2
*
*
*********************************************************************************************************
*/
void UART_InitBuffer (int uart_no)
{
	UART_BUFFER		*pUartBuffer; 
	int				i, result; 
	
	//------------------------------------------------------------------------------
	// get base address of buffer 
	//------------------------------------------------------------------------------
	pUartBuffer = UART_GetBufferBaseAddr (uart_no, &result);

	if (result == UART_CHANNEL_NOT_SUPPORTED)
	{
		return;
	}

	//------------------------------------------------------------------------------
	// init buffer variables
	//------------------------------------------------------------------------------
	pUartBuffer->u16RxState = UART_RX_STATE_IDLE;
	pUartBuffer->u16TxState = UART_TX_STATE_IDLE;
	
	pUartBuffer->u16RxBuffer_HeadIndex = 0; 
	pUartBuffer->u16RxBuffer_TailIndex = 0;
	pUartBuffer->u16TxBuffer_HeadIndex = 0; 
	pUartBuffer->u16TxBuffer_TailIndex = 0; 

	for (i=0; i<UART_MAX_RX_BUFFER; i++)
	{
		pUartBuffer->u8RxBuffer[i] = 0; 
	}

	for (i=0; i<UART_MAX_TX_BUFFER; i++)
	{
		pUartBuffer->u8RxBuffer[i] = 0; 
	}	


}


/**
*********************************************************************************************************
* @ Name : UART_GetBufferBaseAddr
*
* @ Parameter
*		- uart_no : 0~2
*		- pResult
*
* @ Return 
*		- buffer 
*
*
*********************************************************************************************************
*/
UART_BUFFER* UART_GetBufferBaseAddr (int uart_no, int *pResult)
{
	UART_BUFFER 	*pUartBuffer; 
	int				result = UART_CHANNEL_SUPPORTED; 

	switch (uart_no)
	{
	case 0:
		pUartBuffer = &sUart0Buffer; 
		break; 

	case 1:
		pUartBuffer = &sUart1Buffer; 
		break; 		

	case 2:
		pUartBuffer = &sUart2Buffer; 
		break; 

	case 3:
		pUartBuffer = &sUart3Buffer; 
		break; 


	default:
		pUartBuffer = (UART_BUFFER *) 0; 
		result = UART_CHANNEL_NOT_SUPPORTED; 
	}

	*pResult = result; 

	return (pUartBuffer); 
}




/**
*********************************************************************************************************
* @ Name : UART_WriteBuffer 
*
* @ Parameters
*		- uart : 0~2
*
* @ Results
*
*
*********************************************************************************************************
*/
UINT8 UART_WriteBuffer (int uart_no, UINT8 *p_data, UINT32 data_count)
{
	UART_BUFFER			*pUartBuffer; 
	int					status; 

	UINT32				i; 


	//------------------------------------------------------------------------------
	// get buffer address 
	//------------------------------------------------------------------------------	
	pUartBuffer = UART_GetBufferBaseAddr(uart_no, &status);
	if (status == UART_CHANNEL_NOT_SUPPORTED)
	{
		return (UART_TX_BUFFER_ERROR_WRONG_CHANNEL); 
	}



	//------------------------------------------------------------------------------
	// wait until the previous transmission is completed
	//------------------------------------------------------------------------------	
	for (i=0; i<100000; i++)
	{
		if (pUartBuffer->u16TxState == UART_TX_STATE_IDLE) break; 
		//if (pUartBuffer->u16TxBuffer_HeadIndex == pUartBuffer->u16TxBuffer_TailIndex) break; 

	}

	if (i == 100000)
	{
		return (UART_TX_BUFFER_ERROR_WAIT_TIMEOUT); 
	}



	//------------------------------------------------------------------------------
	// buffer <-- data 
	//------------------------------------------------------------------------------
	for (i=0; i<data_count; i++)
	{
		pUartBuffer->u8TxBuffer[i] = *(p_data+i); 
	}

	pUartBuffer->u16TxBuffer_HeadIndex = 0; 
	pUartBuffer->u16TxBuffer_TailIndex = data_count; 


	//------------------------------------------------------------------------------
	// update state 
	//------------------------------------------------------------------------------
	pUartBuffer->u16TxState = UART_TX_STATE_TRANSMIT; 

	
	//------------------------------------------------------------------------------
	// enable TX Interrupt
	//------------------------------------------------------------------------------
	UART_Enable_TX_Interrupt (uart_no, 1); 

	return (UART_TX_BUFFER_SUCCESS); 

}



/**
*********************************************************************************************************
* @ Name : UART_Enable_TX_Interrupt 
*
* @ Parameters
*		- uart_no : 0~2
*
* @ Results
*
*
*********************************************************************************************************
*/
void UART_Enable_TX_Interrupt (int uart_no, int enable)
{
	switch (uart_no)
	{
	
	case 0:
		HAL_UART_ENABLE_TX_INTR(UART0, enable); 
		break; 

	case 1:
		HAL_UART_ENABLE_TX_INTR(UART1, enable); 
		break; 

	case 2:
		HAL_UART_ENABLE_TX_INTR(UART2, enable); 
		break; 	
	}

}



/**
*********************************************************************************************************
* @ Name : UART_GetChar 
*
* @ Parameter
*		- uart_no : 0~2
*
* @ Results
*		- 8-bit data other than "-1"		= success
*		-"-1"						= error 
*
*
* @ Description
*		This function mediates cgetchar() and UART_ReadBuffer(). UART_ReadBuffer is a lower-level function which reads directly
*		an UART data from the UART buffer. 
*
*		UART_GetChar() manipulates the received data. 
*
*			(1) converts the data from 8-bit data to 32-bit data
*			(2) returns "-1" if error occurs.
*
*
*********************************************************************************************************
*/

int UART_GetChar (int uart_no)
{
	int			status;
	int			ch;

	ch = UART_ReadBuffer (uart_no, &status);

	if (status != UART_RX_BUFFER_SUCCESS) ch = -1; 

	return (ch); 

}


/**
*********************************************************************************************************
* @ Name : UART_ReadBuffer 
*
* @ Parameters
*		- uart : 0~2
*
* @ Results
*		[return]
*		- 8-bit unsigned data			= success
*		- 0							= fail (it is qualified by *p_status)
*		
*
*		[*p_status]
*		- UART_RX_BUFFER_SUCCESS					= success 
*		- UART_RX_BUFFER_ERROR_EMPTY				= no available data
*		- UART_RX_BUFFER_ERROR_WRONG_CHANNEL		= wrong UART number
*
*
*********************************************************************************************************
*/
UINT8 UART_ReadBuffer (int uart_no, int *p_status)
{

	UART_BUFFER 		*pUartBuffer; 
	int 				status; 

	UINT8				uart_data; 


	//------------------------------------------------------------------------------
	// get buffer address 
	//------------------------------------------------------------------------------	
	pUartBuffer = UART_GetBufferBaseAddr(uart_no, &status);
	if (status == UART_CHANNEL_NOT_SUPPORTED)
	{
		return (UART_RX_BUFFER_ERROR_WRONG_CHANNEL); 
	}


	//------------------------------------------------------------------------------
	// fetch data 
	//------------------------------------------------------------------------------
#ifdef WARNING_
	m_Temp = pUartBuffer->u16RxBuffer_HeadIndex;	
	if (pUartBuffer->u16RxBuffer_TailIndex == m_Temp)
#else	
	if (pUartBuffer->u16RxBuffer_TailIndex == pUartBuffer->u16RxBuffer_HeadIndex)
#endif		
	{
		uart_data = 0; 
		*p_status = UART_RX_BUFFER_ERROR_EMPTY; 
	}
	else 
	{
		uart_data = pUartBuffer->u8RxBuffer[pUartBuffer->u16RxBuffer_HeadIndex++]; 
		*p_status = UART_RX_BUFFER_SUCCESS; 
	}



	//------------------------------------------------------------------------------
	// adjust 
	//------------------------------------------------------------------------------
	if (pUartBuffer->u16RxBuffer_HeadIndex >= UART_MAX_RX_BUFFER)
	{
		pUartBuffer->u16RxBuffer_HeadIndex = 0; 
	}


	//------------------------------------------------------------------------------
	// return 
	//------------------------------------------------------------------------------
	return (uart_data); 

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UART0_Transmit_Receive_ISR(void)
{
	volatile UINT32		intr_status;
	volatile UINT32		line_status; 


	//------------------------------------------------------------------------------
	// get interrupt identification
	//------------------------------------------------------------------------------
	intr_status = CSP_UART_GET_UnIIR(UART0) & UnIIR_INTR_MASK_NO_DMA; 


	//------------------------------------------------------------------------------
	// line interrupt 
	//------------------------------------------------------------------------------
	if (intr_status == UnIIR_IID_LINE_STATUS)
	{
		line_status = CSP_UART_GET_UnLSR(UART0); 
	}


	//------------------------------------------------------------------------------
	// RX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_RXBUF_READY)
	{
		UART0_ReceiveData_ISR(); 
	}


	//------------------------------------------------------------------------------
	// TX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_TXBUF_EMPTY)
	{
		UART0_TransmitData_ISR(); 
	}


}

void UART0_ReceiveData_ISR (void)
{
	UINT8				rcv_data;
	volatile UINT32		line_status; 
	UINT16				next_index; 


	//------------------------------------------------------------------------------
	// get UART data 
	//------------------------------------------------------------------------------
	rcv_data = CSP_UART_GET_UnRBR(UART0); 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART0))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART0, line_status); 
	}
	else 
	{
		//--------------------------------------------------------------------------
		// get next index
		//--------------------------------------------------------------------------
		next_index = sUart0Buffer.u16RxBuffer_TailIndex + 1; 
		if (next_index >= UART_MAX_RX_BUFFER)
		{
			next_index = 0; 
		}

		//--------------------------------------------------------------------------
		// check if RX buffer is full, and ten store data if buffer space available
		//--------------------------------------------------------------------------
		if (next_index == sUart0Buffer.u16RxBuffer_HeadIndex)
		{
			return; 
		}
		else 
		{
			sUart0Buffer.u8RxBuffer[sUart0Buffer.u16RxBuffer_TailIndex] = rcv_data; 
			sUart0Buffer.u16RxBuffer_TailIndex = next_index; 
		}

	}

}


void UART0_TransmitData_ISR (void)
{
	volatile UINT32			line_status;
	UINT8					send_data; 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART0))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART0, line_status); 
	}



	//------------------------------------------------------------------------------
	// Technical Comments
	//
	//		LSR:TEMT			Transmitter Empty (bit 6)
	//
	//		LSR:THRE			Transmit Holding Register Empty (bit 5)
	//
	//	
	//		When THRE is "1", UART interrupt is invoked. The condition of TEMT doesn't invoke 
	//		UART interrupt. 
	//
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_TX_READY(UART0))
	{

#ifdef WARNING_
		m_Temp = sUart0Buffer.u16TxBuffer_TailIndex;
		if (sUart0Buffer.u16TxBuffer_HeadIndex < m_Temp)	
#else			
		if (sUart0Buffer.u16TxBuffer_HeadIndex < sUart0Buffer.u16TxBuffer_TailIndex)
#endif			
		{
			//----------------------------------------------------------------------
			// have a data to transmit
			//----------------------------------------------------------------------
			send_data = sUart0Buffer.u8TxBuffer[sUart0Buffer.u16TxBuffer_HeadIndex++];
			CSP_UART_SET_UnTHR(UART0, send_data); 
		}
		else
		{
			//----------------------------------------------------------------------
			// transmission done
			//----------------------------------------------------------------------
			HAL_UART_ENABLE_TX_INTR(UART0, 0);

			sUart0Buffer.u16TxBuffer_HeadIndex = 0; 
			sUart0Buffer.u16TxBuffer_TailIndex = 0; 
			sUart0Buffer.u16TxState = UART_TX_STATE_IDLE; 

		}

	}

	
}


#if 0
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UART1_Transmit_Receive_ISR(void)
{
	volatile UINT32		intr_status;
	volatile UINT32		line_status; 


	//------------------------------------------------------------------------------
	// get interrupt identification
	//------------------------------------------------------------------------------
	intr_status = CSP_UART_GET_UnIIR(UART1) & UnIIR_INTR_MASK_NO_DMA; 


	//------------------------------------------------------------------------------
	// line interrupt 
	//------------------------------------------------------------------------------
	if (intr_status == UnIIR_IID_LINE_STATUS)
	{
		line_status = CSP_UART_GET_UnLSR(UART1); 
	}


	//------------------------------------------------------------------------------
	// RX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_RXBUF_READY)
	{
		UART1_ReceiveData_ISR(); 
	}


	//------------------------------------------------------------------------------
	// TX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_TXBUF_EMPTY)
	{
		UART1_TransmitData_ISR(); 
	}


}

void UART1_ReceiveData_ISR (void)
{
	UINT8				rcv_data;
	volatile UINT32		line_status; 
	UINT16				next_index; 


	//------------------------------------------------------------------------------
	// get UART data 
	//------------------------------------------------------------------------------
	rcv_data = CSP_UART_GET_UnRBR(UART1); 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART1))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART1, line_status); 
	}
	else 
	{
		//--------------------------------------------------------------------------
		// get next index
		//--------------------------------------------------------------------------
		next_index = sUart1Buffer.u16RxBuffer_TailIndex + 1; 
		if (next_index >= UART_MAX_RX_BUFFER)
		{
			next_index = 0; 
		}

		//--------------------------------------------------------------------------
		// check if RX buffer is full, and ten store data if buffer space available
		//--------------------------------------------------------------------------
		if (next_index == sUart1Buffer.u16RxBuffer_HeadIndex)
		{
			return; 
		}
		else 
		{
			sUart1Buffer.u8RxBuffer[sUart1Buffer.u16RxBuffer_TailIndex] = rcv_data; 
			sUart1Buffer.u16RxBuffer_TailIndex = next_index; 
		}

	}

}


void UART1_TransmitData_ISR (void)
{
	volatile UINT32			line_status;
	UINT8					send_data; 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART1))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART1, line_status); 
	}



	//------------------------------------------------------------------------------
	// Technical Comments
	//
	//		LSR:TEMT			Transmitter Empty (bit 6)
	//
	//		LSR:THRE			Transmit Holding Register Empty (bit 5)
	//
	//	
	//		When THRE is "1", UART interrupt is invoked. The condition of TEMT doesn't invoke 
	//		UART interrupt. 
	//
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_TX_READY(UART1))
	{
#ifdef WARNING_
		m_Temp = sUart1Buffer.u16TxBuffer_TailIndex;
		if (sUart1Buffer.u16TxBuffer_HeadIndex < m_Temp)
#else
		if (sUart1Buffer.u16TxBuffer_HeadIndex < sUart1Buffer.u16TxBuffer_TailIndex)
#endif			
		{
			//----------------------------------------------------------------------
			// have a data to transmit
			//----------------------------------------------------------------------
			send_data = sUart1Buffer.u8TxBuffer[sUart1Buffer.u16TxBuffer_HeadIndex++];
			CSP_UART_SET_UnTHR(UART1, send_data); 
		}
		else
		{
			//----------------------------------------------------------------------
			// transmission done
			//----------------------------------------------------------------------
			HAL_UART_ENABLE_TX_INTR(UART1, 0);

			sUart1Buffer.u16TxBuffer_HeadIndex = 0; 
			sUart1Buffer.u16TxBuffer_TailIndex = 0; 
			sUart1Buffer.u16TxState = UART_TX_STATE_IDLE; 

		}

	}

	
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UART2_Transmit_Receive_ISR(void)
{
	volatile UINT32		intr_status;
	volatile UINT32		line_status; 


	//------------------------------------------------------------------------------
	// get interrupt identification
	//------------------------------------------------------------------------------
	intr_status = CSP_UART_GET_UnIIR(UART2) & UnIIR_INTR_MASK_NO_DMA; 


	//------------------------------------------------------------------------------
	// line interrupt 
	//------------------------------------------------------------------------------
	if (intr_status == UnIIR_IID_LINE_STATUS)
	{
		line_status = CSP_UART_GET_UnLSR(UART2); 
	}


	//------------------------------------------------------------------------------
	// RX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_RXBUF_READY)
	{
		UART2_ReceiveData_ISR(); 
	}


	//------------------------------------------------------------------------------
	// TX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_TXBUF_EMPTY)
	{
		UART2_TransmitData_ISR(); 
	}


}

void UART2_ReceiveData_ISR (void)
{
	UINT8				rcv_data;
	volatile UINT32		line_status; 
	UINT16				next_index; 


	//------------------------------------------------------------------------------
	// get UART data 
	//------------------------------------------------------------------------------
	rcv_data = CSP_UART_GET_UnRBR(UART2); 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART2))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART2, line_status); 
	}
	else 
	{
		//--------------------------------------------------------------------------
		// get next index
		//--------------------------------------------------------------------------
		next_index = sUart2Buffer.u16RxBuffer_TailIndex + 1; 
		if (next_index >= UART_MAX_RX_BUFFER)
		{
			next_index = 0; 
		}

		//--------------------------------------------------------------------------
		// check if RX buffer is full, and ten store data if buffer space available
		//--------------------------------------------------------------------------
		if (next_index == sUart2Buffer.u16RxBuffer_HeadIndex)
		{
			return; 
		}
		else 
		{
			sUart2Buffer.u8RxBuffer[sUart2Buffer.u16RxBuffer_TailIndex] = rcv_data; 
			sUart2Buffer.u16RxBuffer_TailIndex = next_index; 
		}

	}

}


void UART2_TransmitData_ISR (void)
{
	volatile UINT32			line_status;
	UINT8					send_data; 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART2))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART2, line_status); 
	}



	//------------------------------------------------------------------------------
	// Technical Comments
	//
	//		LSR:TEMT			Transmitter Empty (bit 6)
	//
	//		LSR:THRE			Transmit Holding Register Empty (bit 5)
	//
	//	
	//		When THRE is "1", UART interrupt is invoked. The condition of TEMT doesn't invoke 
	//		UART interrupt. 
	//
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_TX_READY(UART2))
	{
#ifdef WARNING_
		m_Temp = sUart2Buffer.u16TxBuffer_TailIndex;
		if (sUart2Buffer.u16TxBuffer_HeadIndex < m_Temp)	
#else			
		if (sUart2Buffer.u16TxBuffer_HeadIndex < sUart2Buffer.u16TxBuffer_TailIndex)
#endif			
		{
			//----------------------------------------------------------------------
			// have a data to transmit
			//----------------------------------------------------------------------
			send_data = sUart2Buffer.u8TxBuffer[sUart2Buffer.u16TxBuffer_HeadIndex++];
			CSP_UART_SET_UnTHR(UART2, send_data); 
		}
		else
		{
			//----------------------------------------------------------------------
			// transmission done
			//----------------------------------------------------------------------
			HAL_UART_ENABLE_TX_INTR(UART2, 0);

			sUart2Buffer.u16TxBuffer_HeadIndex = 0; 
			sUart2Buffer.u16TxBuffer_TailIndex = 0; 
			sUart2Buffer.u16TxState = UART_TX_STATE_IDLE; 

		}

	}

	
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UART3_Transmit_Receive_ISR(void)
{
	volatile UINT32		intr_status;
	volatile UINT32		line_status; 


	//------------------------------------------------------------------------------
	// get interrupt identification
	//------------------------------------------------------------------------------
	intr_status = CSP_UART_GET_UnIIR(UART3) & UnIIR_INTR_MASK_NO_DMA; 


	//------------------------------------------------------------------------------
	// line interrupt 
	//------------------------------------------------------------------------------
	if (intr_status == UnIIR_IID_LINE_STATUS)
	{
		line_status = CSP_UART_GET_UnLSR(UART3); 
	}


	//------------------------------------------------------------------------------
	// RX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_RXBUF_READY)
	{
		UART3_ReceiveData_ISR(); 
	}


	//------------------------------------------------------------------------------
	// TX interrupt 
	//------------------------------------------------------------------------------
	if (intr_status & UnIIR_IID_TXBUF_EMPTY)
	{
		UART3_TransmitData_ISR(); 
	}


}

void UART3_ReceiveData_ISR (void)
{
	UINT8				rcv_data;
	volatile UINT32		line_status; 
	UINT16				next_index; 


	//------------------------------------------------------------------------------
	// get UART data 
	//------------------------------------------------------------------------------
	rcv_data = CSP_UART_GET_UnRBR(UART3); 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART3))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART3, line_status); 
	}
	else 
	{
		//--------------------------------------------------------------------------
		// get next index
		//--------------------------------------------------------------------------
		next_index = sUart3Buffer.u16RxBuffer_TailIndex + 1; 
		if (next_index >= UART_MAX_RX_BUFFER)
		{
			next_index = 0; 
		}

		//--------------------------------------------------------------------------
		// check if RX buffer is full, and ten store data if buffer space available
		//--------------------------------------------------------------------------
		if (next_index == sUart3Buffer.u16RxBuffer_HeadIndex)
		{
			return; 
		}
		else 
		{
			sUart3Buffer.u8RxBuffer[sUart3Buffer.u16RxBuffer_TailIndex] = rcv_data; 
			sUart3Buffer.u16RxBuffer_TailIndex = next_index; 
		}

	}

}


void UART3_TransmitData_ISR (void)
{
	volatile UINT32			line_status;
	UINT8					send_data; 



	//------------------------------------------------------------------------------
	// check line error again 
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_LINE_ERROR(UART3))
	{
		HAL_UART_CLEAR_LINE_ERROR(UART3, line_status); 
	}



	//------------------------------------------------------------------------------
	// Technical Comments
	//
	//		LSR:TEMT			Transmitter Empty (bit 6)
	//
	//		LSR:THRE			Transmit Holding Register Empty (bit 5)
	//
	//	
	//		When THRE is "1", UART interrupt is invoked. The condition of TEMT doesn't invoke 
	//		UART interrupt. 
	//
	//------------------------------------------------------------------------------
	if (HAL_UART_IS_TX_READY(UART3))
	{
#ifdef WARNING_
		m_Temp = sUart3Buffer.u16TxBuffer_TailIndex;
		if (sUart3Buffer.u16TxBuffer_HeadIndex < m_Temp)
#else			
		if (sUart3Buffer.u16TxBuffer_HeadIndex < sUart3Buffer.u16TxBuffer_TailIndex)
#endif			
		{
			//----------------------------------------------------------------------
			// have a data to transmit
			//----------------------------------------------------------------------
			send_data = sUart3Buffer.u8TxBuffer[sUart3Buffer.u16TxBuffer_HeadIndex++];
			CSP_UART_SET_UnTHR(UART3, send_data); 
		}
		else
		{
			//----------------------------------------------------------------------
			// transmission done
			//----------------------------------------------------------------------
			HAL_UART_ENABLE_TX_INTR(UART3, 0);

			sUart3Buffer.u16TxBuffer_HeadIndex = 0; 
			sUart3Buffer.u16TxBuffer_TailIndex = 0; 
			sUart3Buffer.u16TxState = UART_TX_STATE_IDLE; 

		}

	}

	
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////







#endif
